package com.github.permissiondog.cancanpandroid.repository.impl;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.util.Pair;

import com.github.permissiondog.cancanpandroid.repository.LocalRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


import okhttp3.Cookie;

public class LocalRepositoryImpl implements LocalRepository {

    private LocalRepositoryImpl() {}

    private static LocalRepository INSTANCE;

    public static synchronized LocalRepository getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new LocalRepositoryImpl();
        }
        return INSTANCE;
    }


    @Override
    public void saveCookies(List<Cookie> cookies) {
        var db = MySQLiteOpenHelper.getInstance().getWritableDatabase();
        cookies.forEach(cookie -> {
            var values = new ContentValues();
            values.put("name", cookie.name());
            values.put("value", cookie.value());
            values.put("domain", cookie.domain());
            values.put("path", cookie.path());
            values.put("expiresAt", cookie.expiresAt());
            values.put("secure", cookie.secure() ? 1 : 0);
            values.put("httpOnly", cookie.httpOnly() ? 1 : 0);
            db.replace("cookies", null, values);
        });
    }

    @Override
    public List<Cookie> getCookies() {
        List<Cookie> cookies = new ArrayList<>();
        SQLiteDatabase db = MySQLiteOpenHelper.getInstance().getReadableDatabase();
        Cursor cursor = db.query("cookies", null, null, null, null, null, null);
        while (cursor.moveToNext()) {
            var builder = new Cookie.Builder();
            builder.name(cursor.getString(cursor.getColumnIndexOrThrow("name")))
                    .value(cursor.getString(cursor.getColumnIndexOrThrow("value")))
                    .domain(cursor.getString(cursor.getColumnIndexOrThrow("domain")))
                    .path(cursor.getString(cursor.getColumnIndexOrThrow("path")))
                    .expiresAt(cursor.getLong(cursor.getColumnIndexOrThrow("expiresAt")));
            if (cursor.getInt(cursor.getColumnIndexOrThrow("secure")) == 1) {
                builder.secure();
            }

            if (cursor.getInt(cursor.getColumnIndexOrThrow("httpOnly")) == 1) {
                builder.httpOnly();
            }
            cookies.add(builder.build());
        }
        cursor.close();
        return cookies;
    }

    @Override
    public void deleteAllCookies() {
        var db = MySQLiteOpenHelper.getInstance().getWritableDatabase();
        db.delete("cookies", null, null);
    }

    @Override
    public void setPreference(String key, String value) {
        var db = MySQLiteOpenHelper.getInstance().getWritableDatabase();
        var values = new ContentValues();
        values.put("key", key);
        values.put("value", value);
        var result = db.insertWithOnConflict("preferences", null, values, SQLiteDatabase.CONFLICT_REPLACE);
        if (result == -1) {
            Log.e("database", "设置配置项失败");
        }
    }

    @Override
    public Optional<String> getPreference(String key) {
        var db = MySQLiteOpenHelper.getInstance().getReadableDatabase();
        var cursor = db.query("preferences", null, "`key` = ?", new String[]{key}, null, null, null);
        if (!cursor.moveToNext()) {
            return Optional.empty();
        }

        return Optional.of(cursor.getString(cursor.getColumnIndexOrThrow("value")));
    }

    @Override
    public List<Pair<String, String>> getPreferences() {
        var db = MySQLiteOpenHelper.getInstance().getReadableDatabase();
        var cursor = db.query("preferences", null, null, null, null, null, null);
        List<Pair<String, String>> preferences = new ArrayList<>();
        while (cursor.moveToNext()) {
            var key = cursor.getString(cursor.getColumnIndexOrThrow("key"));
            var value = cursor.getString(cursor.getColumnIndexOrThrow("value"));
            preferences.add(new Pair<>(key, value));
        }
        return preferences;
    }


}
